package com.mhy.crash;


import android.content.Context;
import android.content.Intent;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;

import androidx.annotation.NonNull;

import com.mhy.crash.utils.CrashModel;
import com.mhy.crash.utils.HYCrashUtils;

public class HYCrash implements Thread.UncaughtExceptionHandler {
    private Context mContext;
    private boolean autoShowActivity = false;
    private boolean autoKillCrashApp = false;
    private static HYCrash sInstance;
    private OnCrashListener mOnCrashListener;

    public static HYCrash getInstance(Context context) {
        if (sInstance == null) {
            synchronized (HYCrash.class) {
                if (sInstance == null) {
                    sInstance = new HYCrash(context);
                }
            }
        }
        return sInstance;
    }

    public void setOnCrashListener(OnCrashListener listener) {
        mOnCrashListener = listener;
    }

    public HYCrash autoShowActivity(boolean showActivity) {
        this.autoShowActivity = showActivity;
        return this;
    }

    public HYCrash autoKillApp(boolean killCrashApp) {
        this.autoKillCrashApp = killCrashApp;
        return this;
    }

    private HYCrash(Context context) {
        this.mContext = context;
        //捕获1
        Thread.setDefaultUncaughtExceptionHandler(this);//Thread.UncaughtExceptionHandler  uncaughtException()

        Looper looper;
        looper = Looper.myLooper();
        if (looper == null) {
            looper = context.getMainLooper();
        }
        if (looper == null) {
            looper = Looper.getMainLooper();
        }
        //捕获1
        new Handler(looper).post(() -> {
            while (true) { // Looper.loop()内部是一个死循环，出现异常时loop才会退出，所以这里使用while(true)。
                try {
                    Looper.loop();
                } catch (Throwable e) {
                    //处理自己的逻辑
                    uncaughtException(Thread.currentThread(), e);
                    //不需要跳出循环
                }
            }
        });
    }

    @Override
    public void uncaughtException(Thread t, @NonNull Throwable ex) {
        if (t == Looper.getMainLooper().getThread()) {
            //主线程
            Log.i("HYCrash", "主线程异常 线程名: " + t.getName());
        } else {
            //子线程
            Log.i("HYCrash", "子线程异常 线程名: " + t.getName());
        }
        //回调异常
        callbackCrash(t, ex);
    }

    private boolean isChoreographerException = false;

    private void callbackCrash(Thread t, Throwable ex) {
        Log.e("HYCrash", Log.getStackTraceString(ex));
        if (mOnCrashListener != null) {
            //Throwable cause = ex.getCause();
            mOnCrashListener.onCrash(t, ex);
        }

        //viewrootimpl抛出异常会导致Choreographer挂掉 黑屏无法正常使用， 杀掉当前进程/杀掉黑屏的Activity/清栈
        if (isChoreographerException(ex)) {
            isChoreographerException = true;
            HYCrashUtils.killAct(mContext);
        }

        if (autoShowActivity) {
            showCrashActivity(ex);
        }
        if (isChoreographerException){
            isChoreographerException = false;
            HYCrashUtils.killApp();
        }

        //结束进程之前可以把你程序的注销或者退出代码放在这段代码之前
        if (autoKillCrashApp) {
            //杀掉App进程
            HYCrashUtils.killApp();
        }
    }

    /**
     * 启动显示
     */
    public void showCrashActivity(Throwable e) {
        //显示异常信息 activity
        CrashModel model = HYCrashUtils.parseCrash(mContext, e);
        showCrashActivity(model);
    }

    public void showCrashActivity(CrashModel model) {
        if (autoShowActivity) {
            //显示异常信息 activity
            Intent intent = new Intent(mContext, CrashActivity.class);
            intent.putExtra(CrashActivity.CRASH_MODEL, model);
            intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            if (autoKillCrashApp) {
//            intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK);//清栈 app也就退出了;杀进程可能会自动重启,清栈就不会重启了
                intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
            }
            mContext.startActivity(intent);
        }
    }


    /**
     * 子线程操作UI 异常
     */
    private boolean isThreadException(Throwable e) {
        if (e == null) {
            return false;
        }
        //子线程操作UI 异常  实践不需要kill
        if (e.getClass().getName().equals("android.view.ViewRootImpl$CalledFromWrongThreadException")) {
            return true;
        }
        return isThreadException(e.getCause());
    }

    /**
     * viewrootimpl抛出异常会导致Choreographer挂掉
     */
    private boolean isChoreographerException(Throwable e) {
        if (e == null) {
            return false;
        }
        StackTraceElement[] elements = e.getStackTrace();
        if (elements == null || elements.length == 0) {
            return false;
        }

        for (int i = elements.length - 1; i > -1; i--) {
            if (elements.length - i > 20) {
                return false;
            }
            StackTraceElement element = elements[i];
            //Log.e("HYCrash", "StackTraceElement: " + element.toString());
            // view 绘制异常 android.view.Choreographer.doFrame
            if ("android.view.Choreographer".equals(element.getClassName())
                    && "Choreographer.java".equals(element.getFileName())
                    && "doFrame".equals(element.getMethodName())) {
                return true;
            }
//            if ("android.view.ViewRootImpl".equals(element.getClassName())
//                    && "ViewRootImpl.java".equals(element.getFileName())) {//包含子线程UI  实践不需要kill
//                return true;
//            }
            //生命周期中抛出异常
            if ("android.app.servertransaction.TransactionExecutor".equals(element.getClassName())
                    && "TransactionExecutor.java".equals(element.getFileName())
                    && ("execute".equals(element.getMethodName()))) {
                return true;
            }
        }
        return false;
    }

    public interface OnCrashListener {
        void onCrash(Thread t, Throwable ex);
    }
}
